package com.cinnamon.rss.logic;

import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.cinnamon.rss.model.Feed;
import com.cinnamon.rss.model.Item;
import com.cinnamon.rss.model.User;
import com.cinnamon.rss.repository.FeedRepository;
import com.cinnamon.rss.repository.ItemRepository;
import com.cinnamon.rss.repository.UserRepository;

/**
 * Handles requests for Feeds.
 */
@Controller
public class FeedController {

	@Autowired
	private UserRepository userRepository;

	@Autowired
	private FeedRepository feedRepository;

	@Autowired
	private ItemRepository itemRepository;
	
	/**
	 * Gets all user feeds
	 */
	@RequestMapping(value = "/ffeeds", method = RequestMethod.GET)
	public String getFeedsByUser(Model model) {
		// find the the logined user
		String username = SecurityContextHolder.getContext().getAuthentication().getName();
		User user = userRepository.findOne(username);
		List<Feed> feeds = feedRepository.findByUser(user);
		model.addAttribute("userFeeds", feeds);
		return "feeds_view";
	}

	/**
	 * Gets all items by feed id
	 */
	@RequestMapping(value = "/ffeedItems", method = RequestMethod.GET)
	public String getItemsByFeed(@RequestParam("feedId") long feedId,
			Model model) {		
		Feed feed = feedRepository.findOne(feedId);		
		List<Item> items = feed.getItems();
		for(Item it : items) {System.out.println(it);}
		Collections.reverse(items);
		model.addAttribute("listItems", items);
		return "feedItems_view";
	}

	/**
	 * Displays the form for the 'add feed' request. An rss URL is expected to
	 * be entered in a form field.
	 * @throws java.io.UnsupportedEncodingException
	 */
	@RequestMapping("/addFeedForm")
	public ModelAndView showAddFeedForm() throws UnsupportedEncodingException {
		return new ModelAndView("addFeed_view");
	}

	/**
	 * Parse rss-xml from given URL and show the result of parsing
	 */
	@RequestMapping(value = "/faddFeed", method = RequestMethod.POST)
	public String addFeed(@RequestParam("rss") String feedRss, Model model) {
		String result = "RSS-feed saved successfully.";
		String username = SecurityContextHolder.getContext().getAuthentication().getName();
		User user = null;
		Feed feed = null;
		try {
			user = userRepository.findByUsername(username);
			feed = new RSSFeedParser(feedRss).readFeed();
			if (feed != null && user != null) {
				feed.setUser(user);				
				feedRepository.save(feed);			
			}
		} catch (Throwable re) {
			result = "Ssory. Saving failed.\nPlease, check whether URL is correct.";
			re.printStackTrace();
		}
		model.addAttribute("addResult", result);
		return "addedFeed_view";
	}
	
	//	show updateFeedForm
	@RequestMapping("/updateFeedForm")
	public ModelAndView showUpdateFeedForm() {
		return new ModelAndView("updateFeed_view", "command", new String());
	}
	
	//	update feed
	@RequestMapping(value = "/fupdateFeed", method = RequestMethod.POST)
	public String updateFeed(@RequestParam("title") String feedTitle, Model model) {
		String result = "RSS-feed updated successfully.";
		Feed feed = null;
		Feed temp_feed = null;
		
		try {
			feed = feedRepository.findByTitle(feedTitle);
			temp_feed = (new RSSFeedParser(feed.getRssSourceLink())).readFeed();
			List<Item> old_items = feed.getItems();
			List<Item> new_items = temp_feed.getItems();
			
			//	look over new_items, and add new items to old_items
			//	!!!refactor for a better performance
			for(int i = 0; i < new_items.size(); i++) {
				Item item = (Item) new_items.get(i);
				if(!old_items.contains(item)) {
					old_items.add(item);
				}
			}
			feedRepository.save(feed);
		} catch (Throwable re) {
			result = "Ssory. Updating failed.";
			re.printStackTrace();
		}
		model.addAttribute("updateResult", result);
		return "updatedFeed_view";
	}
	

	/**
	 * Displays the form for the 'delete feed' request. A feed's name is
	 * expected to be entered in a form field.
	 */
	@RequestMapping("/deleteFeedForm")
	public ModelAndView showDeleteFeedForm() {
		return new ModelAndView("delFeed_view", "command", new String());
	}

	@RequestMapping(value = "/fdelFeed", method = RequestMethod.POST)
	public String deleteFeed(@RequestParam("feedTitle") String feedTitle) {
		Feed feed = feedRepository.findByTitle(feedTitle);
		feedRepository.delete(feed);
		return "deletedFeed_view";
	}

	/**
	 * Marks/unmarks an item as stared/unstared
	 */
	@RequestMapping(value = "/fmarkStar", method = RequestMethod.POST)
	public void markStared(@RequestParam("itemId") long itemId) {
		Item item = itemRepository.findOne(itemId);
		if (item.isStartFlag()) {
			item.setStartFlag(false);
		} else {
			item.setStartFlag(true);
		}
	}

	/**
	 * Marks/unmarks an item as read
	 */
	@RequestMapping(value = "/fmarkRead", method = RequestMethod.POST)
	public void markRead(@RequestParam("itemId") long itemId) {
		Item item = itemRepository.findOne(itemId);
		if (item.isReadFlag()) {
			item.setReadFlag(false);
		} else {
			item.setReadFlag(true);
		}
	}

	@RequestMapping(value = "/funregister", method = RequestMethod.GET)
	public void deleteUser() {
		String username = SecurityContextHolder.getContext().getAuthentication().getName();
		User user = userRepository.findByUsername(username);
		if (user != null) {
			Iterator<?> it = feedRepository.findByUser(user).iterator();
			while (it.hasNext()) {
				Feed f = (Feed) it.next();
				feedRepository.delete(f);
			}			
			userRepository.delete(user);
		}
	}
}
